package com.walkerma.library;

import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.telephony.TelephonyManager;


public class NetworkProcess {
	public final static int MSG_IP	= 30123;

	public static boolean isNetworkAvailable(Context context) {
		ConnectivityManager connectivityManager = (ConnectivityManager)
				context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		if(activeNetworkInfo==null) return false;        
		return activeNetworkInfo.isConnected();
	}


	public static boolean isWifiEnabled(Context context){
		WifiManager wifiManager = (WifiManager)
				context.getSystemService(Context.WIFI_SERVICE);	
		return wifiManager.isWifiEnabled();
	} 


	public static boolean isWifiConnected(Context context){
		ConnectivityManager connectivityManager = (ConnectivityManager)
				context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		if(activeNetworkInfo==null) return false;
		if(!activeNetworkInfo.isConnected()) return false;
		if(activeNetworkInfo.getType()==ConnectivityManager.TYPE_WIFI)
			return true;
		else
			return false;
	}

	public static boolean isMobileConnected(Context context) {  
		ConnectivityManager connectivityManager = (ConnectivityManager)
				context.getSystemService(Context.CONNECTIVITY_SERVICE);  
		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		if(activeNetworkInfo==null) return false;
		if(!activeNetworkInfo.isConnected()) return false;
		if(activeNetworkInfo.getType()==ConnectivityManager.TYPE_MOBILE)
			return true;
		else
			return false;
	}


	// called by thread
	public static String getLocalWifiIP(Context context){
		WifiManager wm = (WifiManager) context
				.getSystemService(android.content.Context.WIFI_SERVICE );
		WifiInfo wfInfo = wm.getConnectionInfo();
		int ipAddress = wfInfo.getIpAddress();
		return String.format(Locale.ENGLISH, "%d.%d.%d.%d", 
				(ipAddress & 0xff),
				(ipAddress >> 8 & 0xff), 
				(ipAddress >> 16 & 0xff),
				(ipAddress >> 24 & 0xff));
	}


	// called by thread
	public static String getLocalGprsIP(boolean useIPv4) {
		try {
			List<NetworkInterface> interfaces = Collections.list(
					NetworkInterface.getNetworkInterfaces());
			for (NetworkInterface intf : interfaces) {
				List<InetAddress> addrs = Collections.list(
						intf.getInetAddresses());
				for (InetAddress addr : addrs) {
					if (!addr.isLoopbackAddress()) {
						String sAddr = addr.getHostAddress();
						//boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
						boolean isIPv4 = sAddr.indexOf(':')<0;
						if (useIPv4) {
							if (isIPv4) 
								return sAddr;
						} else {
							if (!isIPv4) {
								//240e:8a:f404:adc2:dcb7:6581:8b66:7ef7%9
								int delim = sAddr.indexOf('%'); // drop ip6 zone suffix
								return delim<0 ? sAddr.toUpperCase(Locale.US) : 
									sAddr.substring(0, delim).
									toUpperCase(Locale.US);
							}
						}
					}
				}
			}
		} catch (Exception ex) { } // for now eat exceptions
		return "";
	}


	public static class ThreadIP extends Thread{
		private Handler mHandler;
		private Context context;
		public ThreadIP(Handler mHandler, Context context) {
			this.mHandler = mHandler;
			this.context = context;
		}		
		public void run(){
			String strIP;
			if (isWifiConnected(context))
				strIP = getLocalWifiIP(context); // TYPE_WIFI
			else
				strIP = getLocalGprsIP(true); // TYPE_MOBILE
			mHandler.obtainMessage(MSG_IP, 0, 0, strIP).sendToTarget();
		}
	}


	//	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
	//	<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />  
	//	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
	//	<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />  
	//	<uses-permission android:name="android.permission.WRITE_SETTINGS" />	
	public static void setMobileDataState(Context context, boolean mobileDataEnabled){
		// only for rooted device	
		try{	    
			TelephonyManager telephonyService = (TelephonyManager) 
					context.getSystemService(Context.TELEPHONY_SERVICE);
			Method setMobileDataEnabledMethod = telephonyService.getClass().
					getDeclaredMethod("setDataEnabled", boolean.class);
			if (null != setMobileDataEnabledMethod)
				setMobileDataEnabledMethod.invoke(
						telephonyService, mobileDataEnabled);
		}
		catch (Exception e){
			e.printStackTrace();
		}
	}


	// tested
	public static boolean getMobileDataState(Context context){
		try{
			TelephonyManager telephonyService = (TelephonyManager) 
					context.getSystemService(Context.TELEPHONY_SERVICE);
			Method getMobileDataEnabledMethod = telephonyService.
					getClass().getDeclaredMethod("getDataEnabled");
			if (null != getMobileDataEnabledMethod){
				boolean mobileDataEnabled = (Boolean) 
						getMobileDataEnabledMethod.invoke(telephonyService);
				return mobileDataEnabled;
			}
		}
		catch (Exception e){
			e.printStackTrace();	    	
		}	
		return false;
	}


	// tested
	public static Boolean isMobileDataEnabled(Context context){
		Object connectivityService = context.getSystemService(
				Context.CONNECTIVITY_SERVICE); 
		ConnectivityManager cm = (ConnectivityManager) connectivityService;

		try {
			Class<?> c = Class.forName(cm.getClass().getName());
			Method m = c.getDeclaredMethod("getMobileDataEnabled");
			m.setAccessible(true);
			return (Boolean)m.invoke(cm);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

}
